package myJs.analysis

import myJs.Implicits._
import myJs.api.Api
import myJs.cps._
import myJs.myPkg.jquery.$
import myJs.myPkg.{MyFetch, SwalOptions, swal}
import myJs.tool.Tool
import org.scalajs.dom.html
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks._
import slinky.core.facade.React
import slinky.web.html._

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import myJs.search.detail.{HFilterCp, MFilterCp}
import shared.Pojo._
import upickle.default._
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import shared.tsPojo.TsPojo
import typings.csstype.csstypeStrings

/**
 * Created by yz on 21/1/2022
 */
@react object ComparisonCp {

  type Props = Unit

  val component = FunctionalComponent[Props] { props =>

    val (geneName, setGeneName) = useState("")
    val (imgSrc, setImgSrc) = useState("")
    val (species, setSpecies) = useState("Hsa")
    val (haps, setHaps) = useState(List("HCC"))
    val (hads, setHads) = useState(List.empty[String])
    val (hbps, setHbps) = useState(List("Normal", "ADJ_HCC"))
    val (hbds, setHbds) = useState(List.empty[String])
    val (testMethod, setTestMethod) = useState("wilcox.test")
    val (isLog, setIsLog) = useState(true)
    val (maps, setMaps) = useState(List("HCC"))
    val (mbps, setMbps) = useState(List("Normal"))
    val (mads, setMads) = useState(List.empty[String])
    val (mbds, setMbds) = useState(List.empty[String])
    val (mams, setMams) = useState(List.empty[String])
    val (mbms, setMbms) = useState(List.empty[String])
    val (datasetMap, setDatasetMap) = useState(SeqMap[String, String]())
    val (mDatasetMap, setMDatasetMap) = useState(SeqMap[String, String]())
    val (modelMap, setModelMap) = useState(SeqMap[String, String]())
    val (geneData, setGeneData) = useState("")

    val speciesMap = List("Hsa", "Mmu").optionMap
    val testMethodMap = List("wilcox.test", "t.test").optionMap

    val formRef = React.createRef[html.Form]

    object FTool {

      def refreshImg = () => {
        import TsPojo.analysis._
        val bv = $(formRef.current).bv
        bv.validate()
        val valid = bv.isValid()
        if (valid) {
          Tool.useLoadingF() { () =>
            val log = if (isLog) "Yes" else "No"
            val request = ComparisonImage.Request(geneName = geneName, species = species, haps = haps, hbps = hbps,
              hads = hads, hbds = hbds, testMethod = testMethod, log = log, maps = maps, mbps = mbps, mads = mads,
              mbds = mbds, mams = mams, mbms = mbms)
            Api.analysis.comparisonImage(request).map { response =>
              if (response.valid) {
                val src = s"data:image/png;base64,${response.base64}"
                setImgSrc(src)
                setGeneData(response.geneData)
              } else {
                val options = SwalOptions(title = "Error", text = response.message, `type` = "error")
                swal(options)
              }
            }
          }
        }
        ()
      }

      def geneNameChange = (v: String) => {
        setGeneName(v)
      }

      def testMethodChange = (v: String) => {
        setTestMethod(v)
      }

      def isLogChange = (v: Boolean) => {
        setIsLog(v)
      }

      def speciesChange = (v: String) => {
        setSpecies(v)
      }

      def hapsChange = (vs: List[String]) => {
        setHaps(vs)
      }

      def hadsChange = (vs: List[String]) => {
        setHads(vs)
      }

      def hbpsChange = (vs: List[String]) => {
        setHbps(vs)
      }

      def hbdsChange = (vs: List[String]) => {
        setHbds(vs)
      }

      def mapsChange = (vs: List[String]) => {
        setMaps(vs)
      }

      def mbpsChange = (vs: List[String]) => {
        setMbps(vs)
      }

      def madsChange = (vs: List[String]) => {
        setMads(vs)
      }

      def mbdsChange = (vs: List[String]) => {
        setMbds(vs)
      }

      def mamsChange = (vs: List[String]) => {
        setMams(vs)
      }

      def mbmsChange = (vs: List[String]) => {
        setMbms(vs)
      }

      def bootstrapValidator = {
        val formJq = $(formRef.current)
        val dict: js.Dictionary[js.Any] = js.Dictionary(
          "feedbackIcons" -> js.Dictionary(
            "valid" -> "glyphicon glyphicon-ok",
            "invalid" -> "glyphicon glyphicon-remove",
            "validating" -> "glyphicon glyphicon-refresh",
          ),
          "fields" -> {
            js.Dictionary(
              "haps" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "hads" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "hbps" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "hbds" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "geneName" -> {
                val info = "Gene Symbol"
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "maps" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "mbps" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "mads" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "mbds" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "mams" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
              "mbms" -> {
                val info = ""
                js.Dictionary(
                  "validators" -> js.Dictionary(
                    "notEmpty" -> js.Dictionary(
                      "message" -> s"${info} is required！"
                    ),
                  )
                )
              },
            )
          }
        )
        formJq.bootstrapValidator(dict)
      }

      def refreshDatasetMap = {
        Api.getFileColumn("hbulk_meta.txt", "Dataset").map { rs =>
          val curDatasetMap = rs.optionMap
          setDatasetMap(curDatasetMap)
          setHads(curDatasetMap.keyList)
          setHbds(curDatasetMap.keyList)
        }
      }

      def refreshMDatasetMap = {
        Api.getFileColumn("mbulk_meta.txt", "Dataset").map { rs =>
          val curDatasetMap = rs.optionMap
          setMDatasetMap(curDatasetMap)
          setMads(curDatasetMap.keyList)
          setMbds(curDatasetMap.keyList)
        }
      }

      def refreshModelMap = {
        Api.getFileColumn("mbulk_meta.txt", "Model_show").map { rs =>
          val curMap = rs.optionMap
          setModelMap(curMap)
          setMams(curMap.keyList)
          setMbms(curMap.keyList)
        }
        ()
      }

      def downloadCsv = () => {
        Tool.downloadCsv(s"${geneName}_comparison.csv", geneData)
      }

      def imageName = s"${geneName}_comparison"

      def downloadPng = () => {
        Tool.downloadPng(imgSrc = imgSrc, fileName = s"${imageName}.png")
      }

      def downloadJpeg = () => {
        Tool.downloadJpeg(imgSrc = imgSrc, fileName = s"${imageName}.jpeg")
      }

      def downloadPdf = () => {
        Tool.downloadPdf(imgSrc = imgSrc, fileName = s"${imageName}.pdf")
      }

      def downloadSvg = () => {
        Tool.downloadSvg(imgSrc = imgSrc, fileName = s"${imageName}.svg")
      }

    }

    useEffect(() => {
      FTool.refreshMDatasetMap
      FTool.refreshModelMap
    }, List()
    )

    useEffect(() => {
      FTool.refreshDatasetMap
    }, List()
    )

    useEffect(() => {
      FTool.bootstrapValidator
    }, List()
    )

    useEffect(() => {
      setGeneName("")
    }, List(species)
    )

    div(id := "comparison",

      div(
        div(style := Style(display = csstypeStrings.flex, width = "100%"),
          div(style := Style(flex = 4.5),

            form(className := "form-horizontal", id := "form", ref := formRef,

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",

                div(style := Style(flex = 2, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(), className := "control-label",
                    "Gene Symbol:"),
                ),
                div(style := Style(flex = 3, height = 34,
                  paddingLeft = 15, paddingRight = 15), className := "col-sm-3",
                  {
                    val url = s"${Api.apiUrl}/gepLiver/analysis/allGene?species=${species}"
                    PureAsyncSelect2Cp(width = "100%", onChange = FTool.geneNameChange, name = "geneName", url = url,
                      value = geneName)
                  }
                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(), className := "control-label",
                    "Species:"),
                ),
                div(style := Style(flex = 3, height = 34, display = csstypeStrings.flex, alignItems = csstypeStrings.center,
                  paddingLeft = 15, paddingRight = 15),
                  PureSelectCp(optionMap = speciesMap, value = species, onChange = FTool.speciesChange)
                ),
              ),

              div(style := Style(display = Tool.b2Display(species == "Hsa")),
                div(style := Style(display = csstypeStrings.flex, marginRight = 15, marginBottom = 5
                ), className := "form-group",

                  div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`,
                    width = "19%"),
                    label(style := Style(paddingTop = 7), className := "control-label",
                      "Select Group A:",
                    ),
                  ),
                  AHFilterCp(phenotypes = haps, phenotypesChange = FTool.hapsChange, datasets = hads,
                    datasetsChange = FTool.hadsChange, pName = "haps", dName = "hads", datasetMap = datasetMap),
                ),

                div(style := Style(display = csstypeStrings.flex, marginRight = 15, marginBottom = 5),
                  className := "form-group",
                  div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`,
                    width = "19%"),
                    label(style := Style(paddingTop = 7), className := "control-label",
                      "Select Group B:",
                    ),
                  ),
                  AHFilterCp(phenotypes = hbps, phenotypesChange = FTool.hbpsChange, datasets = hbds,
                    datasetsChange = FTool.hbdsChange, pName = "hbps", dName = "hbds", datasetMap = datasetMap),
                )

              ),
              div(style := Style(display = Tool.b2Display(species == "Mmu")),

                div(style := Style(display = csstypeStrings.flex, marginRight = 15, marginBottom = 5
                ), className := "form-group",

                  div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`,
                    width = "19%"),
                    label(style := Style(paddingTop = 7), className := "control-label",
                      "Select Group A:",
                    ),
                  ),
                  AMFilterCp(phenotypes = maps, phenotypesChange = FTool.mapsChange, datasets = mads,
                    datasetsChange = FTool.madsChange, pName = "maps", dName = "mads", models = mams,
                    modelsChange = FTool.mamsChange, mName = "mams", datasetMap = mDatasetMap, modelMap = modelMap),
                ),

                div(style := Style(display = csstypeStrings.flex, marginRight = 15, marginBottom = 5
                ), className := "form-group",

                  div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`,
                    width = "19%"),
                    label(style := Style(paddingTop = 7), className := "control-label",
                      "Select Group B:",
                    ),
                  ),
                  AMFilterCp(phenotypes = mbps, phenotypesChange = FTool.mbpsChange, datasets = mbds,
                    datasetsChange = FTool.mbdsChange, pName = "mbps", dName = "mbds", models = mbms,
                    modelsChange = FTool.mbmsChange, mName = "mbms", datasetMap = mDatasetMap, modelMap = modelMap),
                ),

              ),

              div(style := Style(display = csstypeStrings.flex, marginRight = 15), className := "form-group",
                div(style := Style(flex = 2, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(), className := "control-label",
                    "Statistical test:"),
                ),
                div(style := Style(flex = 3, height = 34,
                  paddingLeft = 15, paddingRight = 15), className := "col-sm-3",
                  PureSelectCp(optionMap = testMethodMap, value = testMethod, onChange = FTool.testMethodChange)
                ),
                div(style := Style(flex = 2, display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                  label(style := Style(), className := "control-label",
                    "Log", sub("2"), "(TPM+1):"),
                ),
                div(style := Style(flex = 3, height = 34,
                  paddingLeft = 15, paddingRight = 15), className := "col-sm-3",
                  PureToggleCp(value = isLog, valueChange = FTool.isLogChange)
                ),
              ),

              div(className := "form-group",
                div(className := "actions col-sm-offset-2 col-sm-3",
                  button(style := Style(width = "95%"), `type` := "button", className := "btn btn-primary myAddShow",
                    onClick := FTool.refreshImg,
                    s" Plot"
                    ,
                  ),
                ),
              ),
            ),

          ),
        ),
        hr(),

        div(style := Style(display = Tool.b2Display(imgSrc.nonBlank)),
          div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.center),
            div(style := Style(width = "60%"),
              div(style := Style(display = csstypeStrings.flex, justifyContent = csstypeStrings.`flex-end`),
                a(onClick := FTool.downloadCsv, className := "btn  btn-default", title := "Export data",
                  i(className := "glyphicon glyphicon-export")
                ),
                div(style := Style(marginLeft = 5), className := "btn-group",
                  a(title := "Export image", className := "btn  btn-default idsButton", data - "toggle" := "dropdown",
                    data - "hover" := "dropdown", data - "close-others" := "true", aria - "expanded" := "false",
                    i(className := "fa fa-bars")
                  ),
                  ul(className := "dropdown-menu pull-right",
                    li(
                      a(onClick := FTool.downloadPng, "Download PNG image")
                    ),
                    li(
                      a(onClick := FTool.downloadJpeg, "Download JPEG image")
                    ),
                    li(
                      a(onClick := FTool.downloadPdf, "Download PDF image")
                    ),
                    li(
                      a(onClick := FTool.downloadSvg, "Download SVG image")
                    ),
                  )
                )
              ),
              img(className := "mySvg", id := "boxplotImg", src := imgSrc)
            )
          ),
        )

      )


    )

  }

  object STool {


  }

}
